/*
 * @Author: Wangjun
 * @Date: 2021-08-04 09:23:33
 * @LastEditTime: 2023-08-24 22:28:18
 * @LastEditors: Wangjun
 * @Description: 文件信息
 * @FilePath: \libs\easy\file.go
 * hnxr
 */

package easy

import (
	"bufio"
	"fmt"
	"io"
	"io/fs"
	"os"
	"path/filepath"
	"strings"
)

/**
 * @description: 读取文件数据位字符串
 * @param {string} path
 * @return {*}
 */
func ReadFile(path string) (s string) {
	data, err := os.ReadFile(path)
	if err != nil {
		return
	}
	return string(data)
}

func writeFile(f *os.File, data []byte) (err error) {
	_, err = f.Write(data)
	if err != nil {
		f.Close()
		return
	}
	err = f.Sync()
	if err != nil {
		f.Close()
		return
	}
	err = f.Close()
	return
}

/**
 * @description: 写入文件的权限0644
 * @param {string} name
 * @param {[]byte} data
 * @return {*}
 */
func WriteFile(name string, data []byte) (err error) {
	f, err := os.Create(name)
	if err != nil {
		return
	}

	return writeFile(f, data)
}

// 追加文件内容
func AppendFile(name string, data []byte, perm fs.FileMode) (err error) {
	f, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_APPEND, perm)
	if err != nil {
		return
	}
	return writeFile(f, data)
}

/**
 * @description: 文件信息
 * @param {*}
 * @return {*}
 */
type FileInfo struct {
	Name    string // base name of the file
	Size    string // length in bytes for regular files; system-dependent for others
	Mode    string // file mode bits
	ModTime int64  // modification time
	IsDir   bool   // abbreviation for Mode().IsDir()
}

func ReadDir(path string) (fs []*FileInfo, err error) {
	fis, err := os.ReadDir(path)
	if err != nil {
		return
	}
	fs = make([]*FileInfo, len(fis))
	for i, f := range fis {
		fi := new(FileInfo)
		fi.Name = f.Name()
		fi.IsDir = f.IsDir()
		ii, _ := f.Info()
		if ii != nil {
			fi.Size = BeautifySize(ii.Size())
			fi.ModTime = ii.ModTime().Unix()
			fi.Mode = ii.Mode().String()
		}
		fs[i] = fi
	}
	return
}

/**
 * @description: 创建目录0755，创建文件0644
 * @param {string} path
 * @return {*}
 */
func MkdirAll(path string) (err error) {
	return os.MkdirAll(path, 0755)
}

/**
 * @description: 读取文件全部行数
 * @param {string} path 文件路径
 * @param {string} ignoreBlank 是否忽略空行
 * @return {*}
 */
func ReadLines(path string, ignoreBlank ...bool) (lines []string, err error) {
	f, err := os.Open(path)
	if err != nil {
		return
	}
	defer f.Close()
	ignore := true
	if len(ignoreBlank) > 0 {
		ignore = ignoreBlank[0]
	}
	buf := bufio.NewReader(f)
	for line, err := buf.ReadString('\n'); err == nil || len(line) > 0; line, err = buf.ReadString('\n') {
		line = strings.TrimSpace(line)
		if ignore {
			if line == "" {
				continue
			}
		}
		lines = append(lines, line)
	}
	return
}

/**
 * @description: 获取文件修改时间
 * @param {string} path
 * @return {*}
 */
func GetFileModiTime(path string) (t int64, err error) {
	fi, err := os.Stat(path)
	if err != nil {
		return
	}
	t = fi.ModTime().Unix()
	return
}

/**
 * 拷贝文件夹,同时拷贝文件夹中的文件
 * @param srcPath  		需要拷贝的文件夹路径: D:/test
 * @param destPath		拷贝到的位置: D:/backup/
 */
func CopyDir(srcPath string, destPath string) error {
	os.MkdirAll(srcPath, 0755)
	os.MkdirAll(destPath, 0755)
	srcPath = strings.ReplaceAll(srcPath, "\\", "/")
	destPath = strings.ReplaceAll(destPath, "\\", "/")
	if !strings.HasSuffix(srcPath, "/") {
		srcPath += "/"
	}
	if !strings.HasSuffix(destPath, "/") {
		destPath += "/"
	}

	err := filepath.Walk(srcPath, func(path string, f os.FileInfo, err error) error {
		if f == nil {
			return err
		}
		if !f.IsDir() {
			path = strings.ReplaceAll(path, "\\", "/")
			destNewPath := strings.ReplaceAll(path, srcPath, destPath)
			fmt.Println("Copy file:" + path + " to " + destNewPath)
			CopyFile(path, destNewPath, f)
		}
		return nil
	})
	return err
}

/**
 * @description: 复制文件
 * @param {*} src
 * @param {string} dest
 * @param {os.FileInfo} f
 * @return {*}
 */
func CopyFile(src, dest string, fi ...os.FileInfo) (w int64, err error) {
	dir := filepath.Dir(dest)
	if dir != "" {
		os.MkdirAll(dir, 0755)
	}

	var f os.FileInfo
	if fi != nil && fi[0] != nil {
		f = fi[0]
	} else {
		f, err = os.Stat(src)
		if err != nil {
			return
		}
	}

	srcFile, err := os.Open(src)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer srcFile.Close()

	dstFile, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC, f.Mode())
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	io.Copy(dstFile, srcFile)
	dstFile.Close()
	os.Chtimes(dest, f.ModTime(), f.ModTime())
	return
}
